package com.mike.uaa.server.authentication.codec;


import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.security.SecureRandom;
import java.util.regex.Pattern;

/**
 * @author z zhang
 */
public final class BCryptCredentialEncryptor implements CredentialEncryptor {

    /**
     * bcrypt 正则表达式
     */
    private final Pattern BCRYPT_PATTERN = Pattern.compile("\\A\\$2([ayb])?\\$(\\d\\d)\\$[./0-9A-Za-z]{53}");
    private final int strength;
    private final BCryptVersion version;
    private final SecureRandom random;

    public BCryptCredentialEncryptor() {
        this.version = BCryptVersion.$2B;
        this.strength = 8;
        this.random = new SecureRandom();
    }

    @Override
    public String encrypt(CharSequence plaintext) {
        Assert.notNull(plaintext, "密码不能为空！");
        String salt = getSalt();
        return BCrypt.hashpw(plaintext.toString(), salt);
    }

    @Override
    public boolean matches(CharSequence plaintext, String ciphertext) {
        Assert.isTrue(StringUtils.hasText(plaintext), "明文不能为空！");
        Assert.isTrue(StringUtils.hasText(ciphertext), "密文不能为空！");
        Assert.isTrue(this.BCRYPT_PATTERN.matcher(ciphertext).matches(), "Encoded credentials does not look like BCrypt");
        return BCrypt.checkpw(plaintext.toString(), ciphertext);
    }

    // 加盐
    private String getSalt() {
        return BCrypt.gensalt(this.version.getVersion(), this.strength, this.random);
    }

    public static void main(String[] args) {
        BCryptCredentialEncryptor bCryptCredentialsEncryptor = new BCryptCredentialEncryptor();
        String encrypt = bCryptCredentialsEncryptor.encrypt("123456");
        System.out.println(encrypt);


        System.out.println(bCryptCredentialsEncryptor.BCRYPT_PATTERN.matcher(encrypt).matches());

        System.out.println(bCryptCredentialsEncryptor.matches("123456", encrypt));

    }
}
